package eMdP.classesBasiques;


import com.jme.bounding.BoundingBox;
import com.jme.image.Texture;
import com.jme.math.FastMath;
import com.jme.math.Vector3f;
import com.jme.renderer.ColorRGBA;
import com.jme.renderer.Renderer;
import com.jme.scene.Node;
import com.jme.scene.Spatial;
import com.jme.scene.shape.Box;
import com.jme.scene.state.BlendState;
import com.jme.scene.state.MaterialState;
import com.jme.scene.state.TextureState;
import com.jme.system.DisplaySystem;
import com.jme.util.TextureManager;
import com.jme.util.resource.ResourceLocatorTool;
import com.jme.util.resource.SimpleResourceLocator;
import com.jmetest.physics.Utils;
import com.jmex.physics.DynamicPhysicsNode;
import com.jmex.physics.contact.MutableContactInfo;
import com.jmex.physics.material.Material;

import eMdP.gestors.GestorModels;

/**
 * Paquet, conté tant el nom, com el model com el color del paquet gràficament i el node que controla les físiques. Aquest Paquet,
 * és el que el Personatge llança contra la bústia.
 * 
 * @author Peppino Coorp.
 */
public class Paquet extends Node {
	
	private static final long serialVersionUID = 1L;
	
	private String nom;
	private Spatial model;
	private int color;
	private DynamicPhysicsNode nodeFisic;
	private boolean haEstatLlançat;
	
	private float tempsI;
	private float tempsT;
	
	private boolean mort;
	
	//private int idPersonatge;
	private int idJugador;
	
	/**
	 * Constructor bàsic que només assigna el node i un nom al Paquet
	 * 
	 * @param nom El nom del Paquet
	 * @param color El color que té el Paquet, per tal de poder-lo relacionar amb les Bústies
	 * @param nodeFisic El el node que controla les físiques del Paquet
	 */
	public Paquet(String nom,int color,DynamicPhysicsNode nodeFisic) {
		super(nom);
		setNom(nom);
		setColor(color);
		setNodeFisic(nodeFisic);
		this.nodeFisic.setName("nodeFisic"+nom);
		
		/* Creem una caixa, ja que no ens han donat la ubicació del model, per tant treballem amb una caixa com a Paquet */
		Box b = new Box("ModelPaquet", new Vector3f(0,0,0),0.5f,0.5f,0.5f);
    	
		this.setTextura();
		
    	//this.attachChild(b);
    	b.setModelBound(new BoundingBox());
    	b.updateModelBound();
	    
    	this.attachChild(nodeFisic);
    	setModel(b);
    	this.nodeFisic.generatePhysicsGeometry();
    	setMaterial();
    	nodeFisic.computeMass();

    	this.idJugador=0;
		this.tempsI=0;
		this.tempsT=0;
		this.mort=false;
	}

	/**
	 * @return the idPersonatge
	 */
	public int getIdJugador() {
		return idJugador;
	}

	/**
	 * @param idPersonatge the idPersonatge to set
	 */
	public void setIdJugador(int idPersonatge) {
		this.idJugador = idPersonatge;
	}

	/**
	 * @return el nom
	 */
	public String getNom() {
		return nom;
	}

	/**
	 * @param nom el nom que volem assignar al Paquet
	 */
	public void setNom(String nom) {
		this.nom = nom;
	}

	/**
	 * @return el model
	 */
	public Spatial getModel() {
		return model;
	}

	/**
	 * @param model el model que volem assignar al Paquet
	 */
	public void setModel(Spatial model) {
		this.model = model;
	    this.getNodeFisic().attachChild(this.model);
	}

	/**
	 * @return el color
	 */
	public int getColor() {
		return color;
	}

	/**
	 * @param color el color que volem assignar al Paquet
	 */
	public void setColor(int color) {
		this.color = color;
	}

	/**
	 * @return the nodeFisic
	 */
	public DynamicPhysicsNode getNodeFisic() {
		return nodeFisic;
	}

	/**
	 * @param nodeFisic the nodeFisic to set
	 */
	public void setNodeFisic(DynamicPhysicsNode nodeFisic) {
		this.nodeFisic = nodeFisic;
	}
	
	/**
	 * @return the haEstatLlançat
	 */
	public boolean isHaEstatLlançat() {
		return haEstatLlançat;
	}

	/**
	 * @param haEstatLlançat the haEstatLlançat to set
	 */
	public void setHaEstatLlançat(boolean haEstatLlançat) {
		this.haEstatLlançat = haEstatLlançat;
	}

	
	/*****************  Fi dels Getter & Setters *********************/
	
	
	/**
	 * Metode per fer les físiques d'un Node Actives o no.
	 * @param bolea Per fer les físiques actives o no
	 */
	public void setActive(boolean bolea){
		this.nodeFisic.setActive(bolea);
	}
	
	public void liAfectaLaGravetat(boolean bolea){
		this.nodeFisic.setAffectedByGravity(bolea);
	}
	
	public void addForce(Vector3f forsa){
		this.nodeFisic.addForce(forsa);
	}
	
	public void unrest(){
		this.nodeFisic.unrest();
	}
	
	public void clearDynamics(){
		this.nodeFisic.clearDynamics();
	}
	
	/**
	 * Metode per crear un paquet amb un tipus de material definit per defecte
	 */
	
	public void setMaterial(){
    	
    	//Definim el material del paquet
        final Material customMaterial = new Material( "material-paquet" );
        // Fem el material lleuger
        customMaterial.setDensity( 2f );
        // a material should define contact detail pairs for each other material it could collide with in the scene
        // do that just for the floor material - the DEFAULT material
        MutableContactInfo contactDetails = new MutableContactInfo();
        // Definim el rebot que volem que tingui
        contactDetails.setBounce( 0.01f );
        // Definim el nivell que volem que rellisqui!
        contactDetails.setMu( 100 ); // todo: Float.POSITIVE_INFINITY seems to cause issues on Linux (only o_O)
        // now set that behaviour
        customMaterial.putContactHandlingDetails( Material.DEFAULT, contactDetails );

        // ... Finalment provem el nostre material      
        this.getNodeFisic().setMaterial( customMaterial );
//        this.getNodeFisic().setMaterial( Material.IRON );
        //this.getNodeFisic().setMass(0.5f);
        // don't forget to compute mass from density
        this.getNodeFisic().computeMass();
        
	}
	
	/**
	 * Retornem true si el Paquet te un temps per autodestruirse, fals altrament
	 * @return temps true si tempsT>0, fals altrament
	 */
	public boolean sestaAutodestruint(){
		return this.tempsT>0;
	}
	
	/**
	 * El Paquet s'autodestrueix quan han passat X segons desde que ha tocat un node Estàtic
	 * @param tempsI Instant del temps en que el Paquet ha col·lisionat
	 * @param tempsT Temps total que tardà el Paquet a autodestruir-se
	 */
	public void autodestruirme(float tempsI, float tempsT){
		this.tempsI = tempsI;
		this.tempsT = tempsT;
	}
	
	/**
	 * 
	 */
	public boolean matar(float temps){
		return temps>this.tempsI+this.tempsT;
	}
	
	public void mort(){
		this.mort=true;
	}
	
	public boolean estaMort(){
		return this.mort;
	}
	
	public ColorRGBA color(int color){
		System.out.println("Paquet::ColorRGBA color: "+color);
		ColorRGBA col;
		switch (color) {
		case 0:
			col = new ColorRGBA((100/256f),(4/256f),(5/256f),1); // Vermell
			break;
		case 1:
			col = new ColorRGBA((107/256f),(49/256f),(107/256f),1); // Lila
			break;
		case 2:
			col = new ColorRGBA((8/256f),(70/256f),(5/256f),1); // Verd
			break;
		case 3:
			col = new ColorRGBA((109/256f),(102/256f),(11/256f),1); // Groc
			break;
		default:
			col = new ColorRGBA((0/256f),(0/256f),(0/256f),1); //Per defecte es negre
			break;
		}
		return col;
	}
	
	private void color( Spatial spatial, ColorRGBA color ) {
        final MaterialState materialState = DisplaySystem.getDisplaySystem().getRenderer().createMaterialState();
        materialState.setDiffuse( color );
        if ( color.a < 1 ) {
            final BlendState blendState = DisplaySystem.getDisplaySystem().getRenderer().createBlendState();
            blendState.setEnabled( true );
            blendState.setBlendEnabled( true );
            blendState.setSourceFunction( BlendState.SourceFunction.SourceAlpha );
            blendState.setDestinationFunction( BlendState.DestinationFunction.OneMinusSourceAlpha );
            spatial.setRenderState( blendState );
            spatial.setRenderQueueMode( Renderer.QUEUE_TRANSPARENT );
        }
        spatial.setRenderState( materialState );
    }
	
	private void setTextura()
	{
		String fitxerTextura = "eMdP/altresModels/texturesPaquets/";
		switch(this.color)
		{
			case 0: fitxerTextura += "vermell.png"; break;
			case 1: fitxerTextura += "lila.png"; break;
			case 2: fitxerTextura += "verd.png"; break;
			case 3: fitxerTextura += "groc.png"; break;
			default: fitxerTextura += "gris.png";
				
		}
		DisplaySystem display = DisplaySystem.getDisplaySystem();
    	//System.out.println(fitxerTextura);
    	TextureState ts = display.getRenderer().createTextureState();
		ts.setEnabled(true);
		ts.setTexture(
		TextureManager.loadTexture(
			GestorModels.class.getClassLoader().getResource(fitxerTextura),
			Texture.MinificationFilter.Trilinear,
			Texture.MagnificationFilter.Bilinear)
		);
		this.setRenderState(ts);
	}
}
